/*
 * Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 *    of conditions and the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#ifdef LOSCFG_INOTIFY

#include "asm/atomic.h"
#include "internal.h"
#include "los_task_pri.h"

#include "fs/inotify.h"


static atomic_t g_inotifyNum = ATOMIC_INIT(1);

int InotifyWriteEvent(const char *filePath, int eventType)
{
    if (filePath == NULL) {
        return 0;
    }
    return RecordInfoToObserver(filePath, eventType);
}

void ProcInotifyInit(void)
{
    struct ProcDirEntry *inotify = CreateProcEntry("inotify", S_IFDIR | S_IRWXU | S_IRWXG | S_IROTH, NULL);
    if (inotify == NULL) {
        PRINT_ERR("create /proc/inotify error!\n");
        ProcFreeEntry(inotify);
    }
    return;
}

int DoInotifyInit(void)
{
    char name[NAME_MAX] = {0};
    char filePath[NAME_MAX] = {0};
    int len = 0;

    len = snprintf(name, NAME_MAX, "%s%d", "inotify/inotify", g_inotifyNum);
    if (len < 0) {
        return -1;
    }
    struct ProcDirEntry *curEntry = ProcCreate(name, S_IFREG, NULL, NULL);
    if (curEntry == NULL) {
        return -1;
    }
    atomic_inc(&g_inotifyNum);

    len = snprintf(filePath, NAME_MAX, "%s/%s", "/proc", name);
    if (len < 0) {
        return -1;
    }
    return open(filePath, O_RDWR);
}

int DoInotifyAddWatch(int fd, const char *filePath, uint32_t eventType)
{
    struct Vnode *observerVnode = NULL;
    struct file *filep = NULL;
    struct Vnode* subjectVnode = NULL;
    int wd = -1;

    fs_getfilep(fd, &filep);
    if (filep == NULL) {
        PRINT_ERR("[INOTIFY][DoInotifyAddWatch] fs_getfilep failed\n");
        return -1;
    }

    observerVnode = filep->f_vnode;
    if (observerVnode == NULL) {
        PRINT_ERR("[INOTIFY][DoInotifyAddWatch] Get observerVnode failed\n");
        return -1;
    }

    if (!(eventType & ALL_INOTIFY_BITS)) {
        PRINT_ERR("[INOTIFY][DoInotifyAddWatch] no eventType\n");
        return -1;
    }

    wd = InotifyAddWatchToObserver(observerVnode, filePath, eventType);
    if (wd < 0) {
        return wd;
    }

    VnodeLookup(filePath, &subjectVnode, 0);
    if (subjectVnode == NULL) {
        PRINT_ERR("[INOTIFY][DoInotifyAddWatch]Get subjectVnode failed\n");
        return -1;
    }
    InotifyUpdateWatch(observerVnode, subjectVnode, eventType);
    return wd;
}

int InotifyAddWatchToObserverHead(struct Vnode *observerVnode, const char *filePath, uint32_t eventType)
{
    struct WatchInfo *newWatchItem = NULL;
    struct InotifyEvent *watch = NULL;
    uint32_t pathSize = 0;

    if ((observerVnode == NULL) || (observerVnode->observer == NULL) || (filePath == NULL)) {
        return -1;
    }

    newWatchItem = (struct WatchInfo*)LOS_MemAlloc(m_aucSysMem0, sizeof(struct WatchInfo));
    if (newWatchItem == NULL) {
        return -1;
    }

    pathSize = strlen(filePath) + 1;
    watch = (struct InotifyEvent*)LOS_MemAlloc(m_aucSysMem0, sizeof(struct InotifyEvent) + pathSize);
    if (watch == NULL) {
        (VOID)LOS_MemFree(m_aucSysMem0, newWatchItem);
        newWatchItem = NULL;
        return -1;
    }

    watch->mask = eventType;
    strncpy(watch->name, filePath, pathSize);
    watch->len = pathSize;
    watch->wd = 0;

    newWatchItem->inotifyEvent = watch;
    newWatchItem->next = NULL;

    observerVnode->observer->watchHead = newWatchItem;
    observerVnode->observer->lastWd = 0;
    observerVnode->observer->watchesCount += 1;

    return newWatchItem->inotifyEvent->wd;
}

int InotifyAddWatchToObserverCheckSize(struct Vnode *observerVnode)
{
    struct WatchInfo *currentWatchItem = NULL;
    if ((observerVnode == NULL) || (observerVnode->observer == NULL)) {
        return -1;
    }
    if (observerVnode->observer->watchesCount >= MAX_OBSERVER_WATCH_NUM) {
        currentWatchItem = observerVnode->observer->watchHead;
        if (currentWatchItem == NULL) {
            return -1;
        }
        observerVnode->observer->watchHead = currentWatchItem->next;
        observerVnode->observer->watchesCount -= 1;
        (VOID)LOS_MemFree(m_aucSysMem0, currentWatchItem->inotifyEvent);
        currentWatchItem->inotifyEvent = NULL;
        (VOID)LOS_MemFree(m_aucSysMem0, currentWatchItem);
        currentWatchItem = NULL;
    }
    return 0;
}

int InotifyAddWatchToObserverNotHead(struct Vnode *observerVnode, const char *filePath, uint32_t eventType)
{
    struct WatchInfo *currentWatchItem = NULL;
    struct WatchInfo *newWatchItem = NULL;
    struct InotifyEvent *watch = NULL;
    uint32_t pathSize = 0;

    if ((observerVnode == NULL) || (observerVnode->observer == NULL) || (filePath == NULL)) {
        return -1;
    }

    currentWatchItem = observerVnode->observer->watchHead;
    if (currentWatchItem == NULL) {
        return -1;
    }
    while (currentWatchItem->next != NULL) {
        currentWatchItem = currentWatchItem->next;
    }

    newWatchItem = (struct WatchInfo*)LOS_MemAlloc(m_aucSysMem0, sizeof(struct WatchInfo));
    if (newWatchItem == NULL) {
        return -1;
    }
    pathSize = strlen(filePath) + 1;
    watch = (struct InotifyEvent*)LOS_MemAlloc(m_aucSysMem0, sizeof(struct InotifyEvent) + pathSize);
    if (watch == NULL) {
        (VOID)LOS_MemFree(m_aucSysMem0, newWatchItem);
        newWatchItem = NULL;
        return -1;
    }

    watch->mask = eventType;
    strncpy(watch->name, filePath, pathSize);
    watch->len = pathSize;
    watch->wd = observerVnode->observer->lastWd + 1;

    newWatchItem->inotifyEvent = watch;
    newWatchItem->next = NULL;
    currentWatchItem->next = newWatchItem;
    observerVnode->observer->watchesCount += 1;
    observerVnode->observer->lastWd += 1;

    return watch->wd;
}

int InotifyAddWatchToObserver(struct Vnode *observerVnode, const char *filePath, uint32_t eventType)
{
    struct EventObserver *eventObserver = NULL;
    struct WatchInfo *currentWatchItem = NULL;
    uint32_t pathSize = 0;

    if ((observerVnode == NULL) || (filePath == NULL)) {
        return -1;
    }
    if (observerVnode->observer == NULL) {
        eventObserver = (struct EventObserver*)LOS_MemAlloc(m_aucSysMem0, sizeof(struct EventObserver));
        if (eventObserver == NULL) {
            return -1;
        }
        eventObserver->watchesCount = 0;
        eventObserver->watchHead = NULL;
        observerVnode->observer = eventObserver;
    }

    currentWatchItem = observerVnode->observer->watchHead;
    if (currentWatchItem == NULL) {
        return InotifyAddWatchToObserverHead(observerVnode, filePath, eventType);
    }

    pathSize = strlen(filePath) + 1;
    while ((currentWatchItem != NULL) && (currentWatchItem->inotifyEvent != NULL)) {
        if (!strncmp(filePath, currentWatchItem->inotifyEvent->name, pathSize) &&
            (currentWatchItem->inotifyEvent->mask == eventType)) {
            return currentWatchItem->inotifyEvent->wd;
        }
        currentWatchItem = currentWatchItem->next;
    }

    InotifyAddWatchToObserverCheckSize(observerVnode);
    return InotifyAddWatchToObserverNotHead(observerVnode, filePath, eventType);
}

struct WatchInfo* InotifyGetWatchFromObserver(struct Vnode *observerVnode, int wd)
{
    struct WatchInfo *currentWatchItem = NULL;
    struct InotifyEvent *watch = NULL;
    if ((observerVnode == NULL) || (observerVnode->observer == NULL) ||
        (observerVnode->observer->watchHead == NULL)) {
        return NULL;
    }
    currentWatchItem = observerVnode->observer->watchHead;
    while (currentWatchItem != NULL) {
        watch = currentWatchItem->inotifyEvent;
        if (watch == NULL) {
            currentWatchItem = currentWatchItem->next;
            continue;
        }
        if (watch->wd == wd) {
            return currentWatchItem;
        }
        currentWatchItem = currentWatchItem->next;
    }
    return NULL;
}

int InotifyRmWatchFromObserver(struct Vnode *observerVnode, int wd)
{
    int ret = -1;
    struct WatchInfo *currentWatchItem = NULL;
    struct WatchInfo *preWatchItem = NULL;
    struct InotifyEvent *watch = NULL;
    if ((observerVnode == NULL) || (observerVnode->observer == NULL) ||
        (observerVnode->observer->watchHead == NULL)) {
        return -1;
    }

    currentWatchItem = observerVnode->observer->watchHead;
    watch = currentWatchItem->inotifyEvent;
    if (watch == NULL) {
        return -1;
    }
    if (watch->wd == wd) {
        ret = 0;
        observerVnode->observer->watchHead = currentWatchItem->next;
        observerVnode->observer->watchesCount -= 1;
        (VOID)LOS_MemFree(m_aucSysMem0, watch);
        currentWatchItem->inotifyEvent = NULL;
        watch = NULL;
        (VOID)LOS_MemFree(m_aucSysMem0, currentWatchItem);
        currentWatchItem = NULL;
        return ret;
    }

    preWatchItem = currentWatchItem;
    currentWatchItem = currentWatchItem->next;
    while (currentWatchItem != NULL) {
        watch = currentWatchItem->inotifyEvent;
        if (watch == NULL) {
            preWatchItem = currentWatchItem;
            currentWatchItem = currentWatchItem->next;
            continue;
        }
        if (watch->wd == wd) {
            ret = 0;
            preWatchItem = currentWatchItem->next;
            observerVnode->observer->watchesCount -= 1;
            (VOID)LOS_MemFree(m_aucSysMem0, watch);
            currentWatchItem->inotifyEvent = NULL;
            watch = NULL;
            (VOID)LOS_MemFree(m_aucSysMem0, currentWatchItem);
            currentWatchItem = NULL;
            return ret;
        }
        preWatchItem = currentWatchItem;
        currentWatchItem = currentWatchItem->next;
    }
    return ret;
}

int InotifyUpdateWatch(struct Vnode *observerVnode, struct Vnode *subjectVnode, uint32_t eventType)
{
    bool isFound = false;
    struct VnodeInfo *tmpVnodeInfo = NULL;

    if (observerVnode == NULL || subjectVnode == NULL) {
        PRINT_ERR("[INOTIFY][InotifyUpdateWatch]LOS_MemAlloc failed\n");
        return -1;
    }

    if (subjectVnode->subject == NULL) {
        struct EventSubject *subject = (struct EventSubject *)LOS_MemAlloc(m_aucSysMem0, sizeof(struct EventSubject));
        if (subject == NULL) {
            PRINT_ERR("[INOTIFY][InotifyUpdateWatch]LOS_MemAlloc failed\n");
            return -1;
        }
        subject->count = 0;
        subject->head = NULL;
        subjectVnode->subject = subject;
    }

    tmpVnodeInfo = subjectVnode->subject->head;
    while (1) {
        if (tmpVnodeInfo == NULL) {
            break;
        }
        if (tmpVnodeInfo->observerVnode == observerVnode) {
            isFound = true;
            break;
        }
        if (tmpVnodeInfo->next == NULL) {
            break;
        }
        tmpVnodeInfo = tmpVnodeInfo->next;
    }

    if (!isFound) {
        struct VnodeInfo *newVnodeInfo = (struct VnodeInfo *)LOS_MemAlloc(m_aucSysMem0, sizeof(struct VnodeInfo));
        if (newVnodeInfo != NULL) {
            newVnodeInfo->observerVnode = observerVnode;
            newVnodeInfo->eventType = eventType;
            newVnodeInfo->next = NULL;
        } else {
            PRINT_ERR("[INOTIFY][InotifyUpdateWatch]LOS_MemAlloc failed\n");
            return -1;
        }

        if (tmpVnodeInfo == NULL) {
            subjectVnode->subject->head = newVnodeInfo;
        } else {
            tmpVnodeInfo->next = newVnodeInfo;
        }
    } else {
        tmpVnodeInfo->eventType |= eventType;
    }

    return 0;
}

int DoInotifyRmWatch(int fd, int wd)
{
    struct Vnode *observerVnode = NULL;
    struct file *filep = NULL;
    struct Vnode *subjectVnode = NULL;
    char filePath[NAME_MAX] = {0};
    uint32_t eventType = 0;
    struct WatchInfo *watch = NULL;

    fs_getfilep(fd, &filep);
    if (filep == NULL) {
        PRINT_ERR("[INOTIFY][DoInotifyRmWatch] fs_getfilep failed\n");
        return -1;
    }
    observerVnode = filep->f_vnode;
    if (observerVnode == NULL) {
        PRINT_ERR("[INOTIFY][DoInotifyRmWatch] GetobserverVnode failed\n");
        return -1;
    }

    watch = InotifyGetWatchFromObserver(observerVnode, wd);
    if ((watch == NULL) || (watch->inotifyEvent == NULL)) {
        return -1;
    }
    if (watch->inotifyEvent->len > NAME_MAX) {
        return -1;
    }
    strncpy(filePath, watch->inotifyEvent->name, watch->inotifyEvent->len);
    eventType = watch->inotifyEvent->mask;
    if (!(eventType & ALL_INOTIFY_BITS)) {
        PRINT_ERR("[INOTIFY][DoInotifyAddWatch] no eventType\n");
        return -1;
    }
    VnodeLookup(filePath, &subjectVnode, 0);
    if (subjectVnode == NULL) {
        PRINT_ERR("[INOTIFY][DoInotifyAddWatch]Get subjectVnode failed\n");
        return -1;
    }
    InotifyRmWatchFromObserver(observerVnode, wd);
    return InotifyRmWatch(observerVnode, subjectVnode, eventType);
}

int InotifyRmWatch(struct Vnode *observerVnode, struct Vnode *subjectVnode, uint32_t eventType)
{
    bool isFound = true;
    struct VnodeInfo *currentVnodeInfo = NULL;
    struct VnodeInfo *prevVnodeInfo = NULL;

    if (subjectVnode->subject == NULL) {
        PRINT_ERR("[INOTIFY][InotifyDelWatch] inotify no record\n");
        return -1;
    }

    currentVnodeInfo = subjectVnode->subject->head;
    if (currentVnodeInfo == NULL) {
        PRINT_ERR("[INOTIFY][InotifyDelWatch] inotify no record\n");
        return -1;
    }

    while (currentVnodeInfo->observerVnode != observerVnode) {
        if (currentVnodeInfo->next == NULL) {
            isFound = false;
            break;
        }
        prevVnodeInfo = currentVnodeInfo;
        currentVnodeInfo = currentVnodeInfo->next;
    }

    if (!isFound) {
        return -1;
    }
    currentVnodeInfo->eventType &= (~eventType);

    if (currentVnodeInfo->eventType != 0) {
        return 0;
    }

    if (prevVnodeInfo == NULL) {
        subjectVnode->subject->head = currentVnodeInfo->next;
    } else {
        prevVnodeInfo->next = currentVnodeInfo->next;
    }
    (VOID)LOS_MemFree(m_aucSysMem0, currentVnodeInfo);
    currentVnodeInfo = NULL;

    if (subjectVnode->subject->head != NULL) {
        (VOID)LOS_MemFree(m_aucSysMem0, subjectVnode->subject);
        subjectVnode->subject = NULL;
    }
    return 0;
}

int DoInotifyRead(struct Vnode* observerVnode, char *buf, uint32_t bufSize)
{
    int ret = 0;
    struct EventInfo *curEventInfo = NULL;
    struct InotifyEvent *event = NULL;
    int totalReadSize = 0;
    int eventSize = 0;
    char* curBuf = NULL;

    if ((observerVnode == NULL) || (observerVnode->observer == NULL) ||
        (observerVnode->observer->eventHead == NULL) || (buf == NULL)) {
        return -1;
    }
    curEventInfo = observerVnode->observer->eventHead;
    curBuf = buf;
    do {
        event = curEventInfo->inotifyEvent;
        if (event != NULL) {
            eventSize = sizeof(struct InotifyEvent) + event->len;
            totalReadSize += eventSize;
            if (totalReadSize > bufSize) {
                break;
            }
            memcpy((void *)curBuf, (const void *)event, eventSize);
            curBuf += eventSize;
            ret = totalReadSize;
        }
        curEventInfo = curEventInfo->next;
    } while (curEventInfo != NULL);

    return ret;
}

int DoInotifyWriteHead(struct Vnode* observerVnode, struct Vnode *subjectVnode,
    const char *filePath, uint32_t eventType)
{
    struct EventInfo *newEventItem = NULL;
    struct InotifyEvent *event = NULL;
    uint32_t pathSize = 0;

    if ((observerVnode == NULL) || (observerVnode->observer == NULL) ||
        (subjectVnode == NULL) || (subjectVnode->subject == NULL) || (filePath == NULL)) {
        return -1;
    }

    newEventItem = (struct EventInfo*)LOS_MemAlloc(m_aucSysMem0, sizeof(struct EventInfo));
    if (newEventItem == NULL) {
        return -1;
    }

    pathSize = strlen(filePath) + 1;
    event = (struct InotifyEvent*)LOS_MemAlloc(m_aucSysMem0, sizeof(struct InotifyEvent) + pathSize);
    if (event == NULL) {
        (VOID)LOS_MemFree(m_aucSysMem0, newEventItem);
        newEventItem = NULL;
        return -1;
    }

    event->mask = eventType;
    strncpy(event->name, filePath, pathSize);
    event->len = pathSize;

    newEventItem->inotifyEvent = event;
    newEventItem->next = NULL;

    observerVnode->observer->eventHead = newEventItem;
    subjectVnode->subject->count += 1;

    return 0;
}

int DoInotifyWriteNotHead(struct Vnode* observerVnode, struct Vnode *subjectVnode,
    const char *filePath, uint32_t eventType)
{
    struct EventInfo *newEventItem = NULL;
    struct EventInfo *currentEventItem = NULL;
    struct InotifyEvent *event = NULL;
    uint32_t pathSize = 0;

    if ((observerVnode == NULL) || (observerVnode->observer == NULL) ||
        (subjectVnode == NULL) || (subjectVnode->subject == NULL) || (filePath == NULL)) {
        return -1;
    }

    currentEventItem = observerVnode->observer->eventHead;
    if (currentEventItem == NULL) {
        return -1;
    }
    while (currentEventItem->next != NULL) {
        currentEventItem = currentEventItem->next;
    }

    newEventItem = (struct EventInfo*)LOS_MemAlloc(m_aucSysMem0, sizeof(struct EventInfo));
    if (newEventItem == NULL) {
        return -1;
    }
    pathSize = strlen(filePath) + 1;
    event = (struct InotifyEvent*)LOS_MemAlloc(m_aucSysMem0, sizeof(struct InotifyEvent) + pathSize);
    if (event == NULL) {
        (VOID)LOS_MemFree(m_aucSysMem0, newEventItem);
        newEventItem = NULL;
        return -1;
    }

    event->mask = eventType;
    strncpy(event->name, filePath, pathSize);
    event->len = pathSize;

    newEventItem->inotifyEvent = event;
    newEventItem->next = NULL;
    currentEventItem->next = newEventItem;
    subjectVnode->subject->count += 1;

    return 0;
}

int DoInotifyWriteCheckSize(struct Vnode* observerVnode, struct Vnode *subjectVnode)
{
    struct EventInfo *currentEventItem = NULL;
    if ((observerVnode == NULL) || (observerVnode->observer == NULL) ||
        (subjectVnode == NULL) || (subjectVnode->subject == NULL)) {
        return -1;
    }

    if (subjectVnode->subject->count >= MAX_SUBJECT_EVENT_NUM) {
        currentEventItem = observerVnode->observer->eventHead;
        if (currentEventItem == NULL) {
            return -1;
        }
        observerVnode->observer->eventHead = currentEventItem->next;
        subjectVnode->subject->count -= 1;
        (VOID)LOS_MemFree(m_aucSysMem0, currentEventItem->inotifyEvent);
        currentEventItem->inotifyEvent = NULL;
        (VOID)LOS_MemFree(m_aucSysMem0, currentEventItem);
        currentEventItem = NULL;
    }
    return 0;
}

int DoInotifyWrite(struct Vnode* observerVnode, struct Vnode *subjectVnode, const char *filePath, uint32_t eventType)
{
    struct EventObserver *eventObserver = NULL;
    struct EventInfo *currentEventItem = NULL;

    if ((observerVnode == NULL) || (filePath == NULL)) {
        return -1;
    }
    if (observerVnode->observer == NULL) {
        eventObserver = (struct EventObserver*)LOS_MemAlloc(m_aucSysMem0, sizeof(struct EventObserver));
        if (eventObserver == NULL) {
            return -1;
        }
        eventObserver->eventHead = NULL;
        observerVnode->observer = eventObserver;
    }

    currentEventItem = observerVnode->observer->eventHead;
    if (currentEventItem == NULL) {
        return DoInotifyWriteHead(observerVnode, subjectVnode, filePath, eventType);
    }

    DoInotifyWriteCheckSize(observerVnode, subjectVnode);
    return DoInotifyWriteNotHead(observerVnode, subjectVnode, filePath, eventType);
}

int InotifyVnodeFree(struct Vnode *vnode)
{
    struct EventInfo *rmEventItem = NULL;
    struct EventInfo *currentEventItem = NULL;
    struct WatchInfo *rmWatchItem = NULL;
    struct WatchInfo *currentWatchItem = NULL;
    struct VnodeInfo *currentVnodeItem = NULL;
    struct VnodeInfo *rmVnodeItem = NULL;

    if (vnode == NULL) {
        return LOS_OK;
    }
    if (vnode->observer != NULL) {
        currentEventItem = vnode->observer->eventHead;
    }
    while (currentEventItem != NULL) {
        rmEventItem = currentEventItem;
        currentEventItem = currentEventItem->next;
        (VOID)LOS_MemFree(m_aucSysMem0, rmEventItem->inotifyEvent);
        rmEventItem->inotifyEvent = NULL;
        (VOID)LOS_MemFree(m_aucSysMem0, rmEventItem);
        rmEventItem = NULL;
    }

    if (vnode->observer != NULL) {
        currentWatchItem = vnode->observer->watchHead;
    }
    while (currentWatchItem != NULL) {
        rmWatchItem = currentWatchItem;
        currentWatchItem = currentWatchItem->next;
        (VOID)LOS_MemFree(m_aucSysMem0, rmWatchItem->inotifyEvent);
        rmWatchItem->inotifyEvent = NULL;
        (VOID)LOS_MemFree(m_aucSysMem0, rmWatchItem);
        rmWatchItem = NULL;
    }
    (VOID)LOS_MemFree(m_aucSysMem0, vnode->observer);
    vnode->observer = NULL;

    if (vnode->subject != NULL) {
        currentVnodeItem = vnode->subject->head;
    }
    while (currentVnodeItem != NULL) {
        rmVnodeItem = currentVnodeItem;
        currentVnodeItem = currentVnodeItem->next;
        (VOID)LOS_MemFree(m_aucSysMem0, rmVnodeItem);
        rmVnodeItem = NULL;
    }
    (VOID)LOS_MemFree(m_aucSysMem0, vnode->subject);
    vnode->subject = NULL;

    return LOS_OK;
}

int RecordInfoToObserver(const char *filePath, uint32_t eventType)
{
    int ret = 0;
    struct Vnode *subjectVnode = NULL;
    struct Vnode *observerVnode = NULL;
    struct VnodeInfo *eventList = NULL;

    VnodeLookup(filePath, &subjectVnode, 0);
    if ((subjectVnode == NULL) || (subjectVnode->subject == NULL) || (subjectVnode->subject->head == NULL)) {
        return -1;
    }
    eventList = subjectVnode->subject->head;
    while (eventList != NULL) {
        observerVnode = eventList->observerVnode;
        if (eventType & eventList->eventType) {
            ret = DoInotifyWrite(observerVnode, subjectVnode, filePath, eventType);
        }
        eventList = eventList->next;
    }

    return ret;
}
#endif